import time
import requests
from datetime import datetime
import math
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib

listJZ = []
list_time = []


def get_gz_history(fund_code):
    for i in range(0, 24):  # 爬取12个月的历史净值
        url = f"http://api.fund.eastmoney.com/f10/lsjz?fundCode={fund_code}&pageIndex={i + 1}&pageSize=20"
        headers = {
            'Referer': 'http://fundf10.eastmoney.com',
            'User-Agent': 'Mozilla/5.0'
        }
        r = requests.get(url, headers=headers, timeout=20)
        data = r.json()['Data']['LSJZList']
        for get_ls_num in range(len(data)):
            listJZ.append(float(data[get_ls_num]['DWJZ']))  # 保存所有历史净值
            list_time.append(data[get_ls_num]['FSRQ'])  # 保存最近更新的历史净值的时间


if __name__ == '__main__':
    jj_rc = pd.read_excel(r'../Fund_form_files/JJ_bd.xlsx', dtype={'基金代码': str, '基金名称': str, '板块': str})
    jj_code = jj_rc['基金代码'].values
    jj_name = jj_rc['基金名称'].values
    jj_type = jj_rc['板块'].values
    for code in range(len(jj_code)):
        print(f'正在模拟交易{jj_name[code]}({jj_code[code]})')
        get_gz_history(jj_code[code])
        cash = 20000
        ben_mon = 20000
        int_ben_mon = 20000
        inventory = 0
        day = len(listJZ) - 1
        buy_records = []
        num = 0  # 累计操作次数
        ma5_ok = ''
        ma20_ok = ''
        up_ok = ''
        low_ok = ''
        ma5_big_ma20 = '🈚'
        upper_band = 0
        lower_band = 0
        with open(f'回测表/{code+1}{jj_name[code]}({jj_type[code]})', 'w', encoding='utf-8') as f2:
            f2.write(f'{jj_name[code]}({jj_type[code]})\n')
            for j in range(len(listJZ)):
                action = ''
                yle = cash - ben_mon
                price = listJZ[day]
                # ============================================================
                if day < len(listJZ) - 1:
                    zf = (price - listJZ[day + 1]) / listJZ[day + 1] * 100
                else:
                    zf = 0
                if day < len(listJZ) - 5:
                    ma5 = sum(listJZ[-(len(listJZ) - day - 1):][:5]) / 5
                    if price > ma5:
                        ma5_ok = '⬆️'
                    else:
                        ma5_ok = '⬇️'
                else:
                    ma5 = 0
                if day < len(listJZ) - 10:
                    ma10 = sum(listJZ[-(len(listJZ) - day - 1):][:10]) / 10
                    if price > ma10:
                        ma10_ok = '⬆️'
                    else:
                        ma10_ok = '⬇️'
                else:
                    ma10 = 0
                if day < len(listJZ) - 20:
                    ma20 = sum(listJZ[-(len(listJZ) - day - 1):][:20]) / 20
                    if price > ma20:
                        ma20_ok = '⬆️'
                    else:
                        ma20_ok = '⬇️'
                else:
                    ma20 = 0
                # --------------------------------
                if ma5 != 0 and ma20 != 0 and ma10 != 0:
                    if day < len(listJZ) - 6:  # 确保有足够数据计算前一天的MA
                        today_ma5 = sum(listJZ[-(len(listJZ) - day):][:5]) / 5  # 前一天的MA5
                    else:
                        today_ma5 = 0
                    if day < len(listJZ) - 11:  # 确保有足够数据计算前一天的MA
                        today_ma10 = sum(listJZ[-(len(listJZ) - day):][:10]) / 10  # 前一天的MA5
                    else:
                        today_ma10 = 0
                    if day < len(listJZ) - 21:  # 确保有足够数据计算前一天的MA20
                        today_ma20 = sum(listJZ[-(len(listJZ) - day):][:20]) / 20  # 前一天的MA20
                    else:
                        today_ma20 = 0
                    # --------------------------------`
                    my_bz_c = math.sqrt(
                        sum((x - ma20) ** 2 for x in listJZ[-(len(listJZ) - day - 1):][:20]) / 20)  # 计算20日标准差(波动率)
                    my_bz_c5 = math.sqrt(
                        sum((x - ma5) ** 2 for x in listJZ[-(len(listJZ) - day - 1):][:5]) / 5)  # 计算5日标准差(波动率)
                    upper_band = ma20 + 2 * my_bz_c  # 布林带上轨 = 中轨 + 2倍标准差
                    lower_band = ma20 - 2 * my_bz_c  # 布林带下轨 = 中轨 - 2倍标准差
                    if today_ma5 != 0 and today_ma20 != 0:
                        # 金叉条件：今日ma5>ma20 且 昨日ma5<=ma20
                        if ma5 < ma20 and today_ma5 > today_ma20 and price < upper_band:
                            cross_signal = "💰金叉"
                            f2.write(f'💰金叉\n')
                            action = '1'
                        # 死叉条件：今日ma5<ma20 且 昨日ma5>=ma20
                        elif ma5 > ma20 and today_ma5 < today_ma20:
                            cross_signal = "💀死叉"
                            f2.write(f'💀死叉\n')
                        else:
                            cross_signal = "➖无交叉"
                            action = ''
                    else:
                        cross_signal = "📊数据不足"
                        action = ''
                    if price >= upper_band:
                        up_ok = '✔️'
                        low_ok = '❌'
                    elif price <= lower_band:
                        low_ok = '✔️'
                        up_ok = '❌'
                    else:
                        up_ok = '❌'
                        low_ok = '❌'
                    if ma5 > ma20:
                        ma5_big_ma20 = '✔️'
                    else:
                        ma5_big_ma20 = '❌'
                # ============================================================
                begin_day = datetime.strptime(list_time[len(listJZ) - 1], "%Y-%m-%d")
                now_day = datetime.strptime(list_time[day], "%Y-%m-%d")
                tz_days = now_day - begin_day
                print(f'🧐今天是{list_time[day]}号==第{tz_days.days}天===')
                print(f"🛒净值: ${price} | 涨幅：{zf:.2f}%")
                print(f"💹MA5: ${ma5:.4f}{ma5_ok} | MA20：${ma20:.4f}{ma20_ok}|MA5>MA20❔{ma5_big_ma20}")
                print(f"💹Up: ${upper_band:.4f}{up_ok}| Low：${lower_band:.4f}{low_ok}")
                print(f"💰现金: ${cash:.2f}")
                print(f"📈盈利: ${yle:.2f}")
                print(f"📦库存: {inventory:.3f}")
                if len(buy_records) != 0:
                    max_jz = buy_records[0]['price']
                    min_jz = buy_records[len(buy_records) - 1]['price']
                    # 计算总投入金额和总股数
                    total_amount = sum(record['amount'] for record in buy_records)
                    total_quantity = sum(record['quantity'] for record in buy_records)
                    average_cost = total_amount / total_quantity if total_quantity > 0 else 0
                    cb_cy = (price - average_cost) / average_cost * 100
                    if cb_cy >= 8:
                        xh = '✅'
                    else:
                        xh = '❎'
                    print(f"成本：{average_cost:.3f}|总盈亏：{cb_cy:.2f}% {xh}")
                    print(f"最高价：{max_jz}|最高价涨幅：{(price - max_jz) / max_jz * 100:.2f}%")
                    print(f"最低价：{min_jz}|最低价涨幅：{(price - min_jz) / min_jz * 100:.2f}%")
                print("\n买入记录:")
                for record in buy_records:
                    date1 = datetime.strptime(record['time'], "%Y-%m-%d")
                    date2 = datetime.strptime(list_time[day], "%Y-%m-%d")
                    day_c = (date2 - date1).days
                    print(
                        f"      时间差：{day_c}天,金额:${record['amount']:.2f}, "
                        f"单价:{record['price']}, 份额:{record['quantity']:.3f}")
                    if day_c >= 7:
                        action = '2'
                if action == '1':
                    num = num + 1
                    amount = 10000
                    if amount <= cash:
                        quantity = amount / price
                        inventory += quantity
                        cash -= amount
                        buy_records.append({
                            'amount': amount,
                            'price': price,
                            'quantity': quantity,
                            'time': list_time[day]
                        })
                        print(f"购买了 {quantity:.2f} 单位")
                        f2.write(
                            f'买入时间{list_time[day]}\n20日波动率{my_bz_c * 100:.2f}%\n5日波动率{my_bz_c5 * 100:.2f}%\n')
                    else:
                        print("现金不足")
                    input('Enter继续')
                elif action == '2':
                    num = num + 1
                    cash += inventory * price * (1 - 0.005)
                    print(f'本金${ben_mon},剩余本金${cash},清仓净值{price},'
                          f'清空库存结余{inventory * price * (1 - 0.005):.2f}$')
                    end_yl = cash - ben_mon
                    syl = (cash - ben_mon) / ben_mon * 100
                    print(f'投资{tz_days.days}天以来收益${end_yl:.2f},期间买卖{num}次')
                    if len(buy_records) != 0:
                        buy_records.clear()
                        inventory = 0
                    f2.write(f'卖出时间{list_time[day]}\n')
                    f2.write(
                        f'本金${ben_mon:.2f},剩余本金${cash:.2f},这一轮收益{end_yl:.2f}率{syl:.2f}%,'
                        f'总体收益{cash - int_ben_mon:.2f}率{(cash - int_ben_mon) / int_ben_mon * 100:.2f}%\n'
                        f'=======================================\n')
                    ben_mon = cash
                    input('Enter继续')

                day = day - 1
            listJZ.clear()
